package org.vaadin.nf4v.ext.config.menu;

import org.vaadin.nf4v.core.config.PageConfig;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

/**
 * Menu item object represents page or window menu item.
 * Menu items compose a menu tree which represents complete context menu.
 */
public class MenuItemDescription implements Serializable{
    private String name;
    private String[] path;
    private int weight;
    private String icon;
    private boolean separate;
    private MenuItemDescription parent;
    private List<MenuItemDescription> childs = new LinkedList<MenuItemDescription>();
    private boolean isCommandItem;
    private boolean contextSensitive;
    private PageConfig config;
    private String context;

    /**
     * Item name may be composite, e.g. "Administration/Control/Users".
     *
     * @return menu item name
     */
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**
     * Each menu item name token represents navigation level. (e.g. in case of menu it is submenu)
     *
     * @return array of menu item name tokens
     */
    public String[] getPath() {
        return path;
    }

    public void setPath(String[] path) {
        this.path = path;
    }

    /**
     * @return true indicates separator requirement before menu item.
     */
    public boolean isSeparate() {
        return separate;
    }

    public void setSeparate(boolean separate) {
        this.separate = separate;
    }

    /**
     * By default menu items are sorted by name.
     * Weight adds additional sorting. Items with higher weight
     * are placed lower items with lighter weight.
     *
     * @return return menu item weight.
     */
    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    /**
     * @return menu item icon source path
     */
    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }

    /**
     * Root item may not contain name (if @Menu annotation wasn't set for context).
     * In this case it is used just as menu tree root and should never be rendered in real menu
     *
     * @return parent menu item or null if current item is root
     */
    public MenuItemDescription getParent() {
        return parent;
    }

    public void setParent(MenuItemDescription parent) {
        this.parent = parent;
    }

    /**
     * @return list of child menu items or empty list if current item is leaf
     */
    public List<MenuItemDescription> getChilds() {
        return childs;
    }

    public void setChilds(List<MenuItemDescription> childs) {
        this.childs = childs;
    }

    /**
     * During parsing navigation path "empty" menu items may be created.
     * They represent just folding submenu.
     *
     * @return true if current item holds navigation command, false if current item is grouping node.
     */
    public boolean isCommandItem() {
        return isCommandItem;
    }

    public void setCommandItem(boolean commandItem) {
        isCommandItem = commandItem;
    }

    /**
     * Context sensitive means that this menu item will work only in it's context.
     * If context sensitive is false then menu item will switch context if necessary.
     *
     * @return true if menu item is context sensitive, false otherwise
     */
    public boolean isContextSensitive() {
        return contextSensitive;
    }

    public void setContextSensitive(boolean contextSensitive) {
        this.contextSensitive = contextSensitive;
    }

    /**
     * Only leafs have not null config.
     *
     * @return page config associated with item
     */
    public PageConfig getConfig() {
        return config;
    }

    public void setConfig(PageConfig config) {
        this.config = config;
    }

    /**
     * @return context name of this menu item
     */
    public String getContext() {
        return context;
    }

    public void setContext(String context) {
        this.context = context;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        MenuItemDescription that = (MenuItemDescription) o;

        if (context != null ? !context.equals(that.context) : that.context != null) return false;
        return !(name != null ? !name.equals(that.name) : that.name != null);

    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (context != null ? context.hashCode() : 0);
        return result;
    }
}
